import javax.microedition.lcdui.*;
import java.io.InputStream;

#define Read32() (int)(data[offset++]&0xFF) | ((data[offset++]&0xFF)<<8) | ((data[offset++]&0xFF)<<16) | ((data[offset++]&0xFF)<<24)

#define Read16() (short)((data[offset++]&0xFF) | ((data[offset++]&0xFF)<<8))

#define Read8() (byte)(data[offset++]&0xFF)

#define ReadARGB() ((data[offset++]&0xFF)<<16) | ((data[offset++]&0xFF)<<8) | (data[offset++]&0xFF) | ((data[offset++]&0xFF)<<24)

#include "defines.h"
public class ASprite
{
	final int SPRIRE_MASK = 0xFF00FF00;
	private short m_sVersion = 0;
	private byte m_bFormatType;
	private int m_iFileSize;
	private int m_iModulesNo;
	private int m_iFramesNo;
	private int m_iAnimationsNo;
	private byte m_bNoPalettes;
	
	private int offset = 0;
	
	private int[] m_aModulesX = null;
	private int[] m_aModulesY = null;
	private int[] m_aModulesW = null;
	private int[] m_aModulesH = null;
	
	private int[] m_aFModuleNo = null;
	private int[][] m_aFModuleIndex = null;
	private int[][] m_aFModuleOX = null;
	private int[][] m_aFModuleOY = null;
	private byte[][] m_aFModuleFlags = null;
	
	private byte[] data;
	// private int[][] m_aaModulesData = null;
	private Image[] m_imgModules = null;
	
	ASprite(){};
	
	boolean LoadSprite(String name)
	{
		offset = 0;
		try
		{
			System.gc();
			InputStream is = this.getClass().getResourceAsStream(name);
			m_iFileSize = is.available();
			
#ifdef USE_DEBUG_SPRITE_LOADING
			System.out.println("File Size: "+m_iFileSize);
#endif
			
			data = new byte[m_iFileSize];
			is.read(data);
			
			// === Read Sprite Header ===
			// read sprite mask check
			int mask = Read32();
			System.out.println(">>>>>>>>>>>>>>>>mask: "+mask);
			if(SPRIRE_MASK != mask)
			{
				System.out.println("Not sprite format file!");
				return false;
			}
			
			m_sVersion = Read16();
			
			// read for type of sprite
			m_bFormatType = Read8();
#ifdef USE_DEBUG_SPRITE_LOADING
			System.out.println("Format type: "+m_bFormatType);
#endif

			// === Read data header ===
			if(m_bFormatType == 2)
				m_bNoPalettes = Read8();	//number of palette
			m_iModulesNo = Read32();
			m_iFramesNo = Read32();
			m_iAnimationsNo = Read32();
			
			// === Read sprite data ===
			LoadModules();
			LoadFrames();
			LoadModulesData();
		}
		catch(Exception e)
		{
			System.out.println("LoadSprite error info: " + e);
			return false;
		}
		data = null;
		System.gc();
		return true;
	}
	
	private int LoadModules()
	{
// #ifdef USE_DEBUG_SPRITE_LOADING
		// System.out.println("Number of Modules: "+m_iModulesNo);
// #endif
		if(m_iModulesNo > 0)
		{			
			m_aModulesW = new int[m_iModulesNo];
			m_aModulesH = new int[m_iModulesNo];

			// m_imgModules = new Image[m_iModulesNo];
			
			for(int i=0; i<m_iModulesNo; i++)
			{
				m_aModulesW[i] = Read32();
				m_aModulesH[i] = Read32();
			}
		}
		return offset;
	}
	
	private int LoadFrames()
	{
		m_aFModuleNo = new int[m_iFramesNo];
		m_aFModuleIndex = new int[m_iFramesNo][];
		m_aFModuleOX = new int[m_iFramesNo][];
		m_aFModuleOY = new int[m_iFramesNo][];
		m_aFModuleFlags = new byte[m_iFramesNo][];
		
		for(int i=0; i<m_iFramesNo; i++)
		{
			m_aFModuleNo[i] = Read32();
			m_aFModuleIndex[i] = new int[m_aFModuleNo[i]];
			m_aFModuleOX[i] = new int[m_aFModuleNo[i]];
			m_aFModuleOY[i] = new int[m_aFModuleNo[i]];
			m_aFModuleFlags[i] = new byte[m_aFModuleNo[i]];
			for(int j=0; j<m_aFModuleNo[i]; j++)
			{
				m_aFModuleIndex[i][j] = Read32();
				m_aFModuleOX[i][j] = Read32();
				m_aFModuleOY[i][j] = Read32();
				m_aFModuleFlags[i][j] = Read8();
			}
		}
		
		return offset;
	}
	
	private boolean LoadModulesData()
	{
		if(m_iModulesNo <= 0)
			return false;
		int uuu=0;
		try{
			m_imgModules = new Image[m_iModulesNo];
			int length = 0;
			int[] img_data = null;
			
			for(int i=0; i<m_iModulesNo; i++)
			{
				length = m_aModulesW[i] * m_aModulesH[i];
				img_data = new int[length];

				for(int k=0; k<length; k++)
				{
					img_data[k] = ReadARGB();
				}
				
				m_imgModules[i] = Image.createRGBImage(img_data, m_aModulesW[i], m_aModulesH[i], true);
				img_data = null;
			}
		}catch(Exception ex){		
			System.out.println("ERROR load data: "+ex);
			return false;
		}
		return true;
	}
	
	int NumOfModules()
	{
		return m_iModulesNo;
	}
	
	byte FormatType()
	{
		return m_bFormatType;
	}
	
	void PaintModule(Graphics g, int id, int x, int y)
	{
		if(m_imgModules[id] != null)
			g.drawImage(m_imgModules[id], x, y, 0);
		else
			System.out.println("NULL");
	}
	
	void PaintFrame(Graphics g, int fID, int x, int y)
	{
		if(fID<0 || fID>m_iFramesNo)
		{
			System.out.println("ERROR: out of frames list ["+fID+"]");
			return;
		}
		int k=0;
		try{
		for(int i=0; i<m_aFModuleNo[fID]; i++)
		{
			k=i;
			g.drawImage(m_imgModules[m_aFModuleIndex[fID][i]], 
						x + m_aFModuleOX[fID][i],
						y + m_aFModuleOY[fID][i],
						0);
		}
		}catch(Exception ex)
		{
			System.out.println("ERROR: i="+k);
		}
	}
	
	void PrintInfo()
	{
		System.out.println("Version: "+m_sVersion);
		System.out.println("Sprite format type: "+m_bFormatType);
		System.out.println("Sprite size:        "+m_iFileSize);
		System.out.println("Number of Modules:  "+m_iModulesNo);
		System.out.println("Number of Frames:  "+m_iFramesNo);
		System.out.println("Number of Animations:  "+m_iAnimationsNo);
		
		System.out.println("*** Frame info ***");
		for(int i=0; i<m_iFramesNo; i++)
		{
			System.out.println("+Frame "+i+":");
			for(int j=0; j<m_aFModuleNo[i]; j++)
			{
				System.out.println("---FModules: "+j);
				System.out.println("		Index: "+m_aFModuleIndex[i][j]);
				System.out.println("		OX	 : "+m_aFModuleOX[i][j]);
				System.out.println("		OY	 : "+m_aFModuleOY[i][j]);
				System.out.println("		Flags: "+m_aFModuleFlags[i][j]);
			}
		}
	}
	
	void Free()
	{
		data = null;
		m_aModulesX = null;
		m_aModulesY = null;
		m_aModulesW = null;
		m_aModulesH = null;
		
		m_aFModuleIndex = null;
		m_aFModuleNo = null;
		m_aFModuleOX = null;
		m_aFModuleOY = null;
		m_aFModuleFlags = null;
		
		m_imgModules = null;
		
		System.gc();
	}
}